package org.jeecg.modules.simulator.model;


import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.simulator.model.orbit.OrbitPoint;
import org.jeecg.modules.simulator.model.person.Person;
import org.jeecg.modules.simulator.model.train.*;
import org.jeecg.modules.simulator.model.train.action.ExecutionStatus;
import org.jeecg.modules.simulator.model.train.action.TrainActionRecorder;
import org.jeecg.modules.simulator.model.train.action.TrainActionRecorders;
import org.jeecg.modules.simulator.model.train.event.TrainStopEvent;
import org.jeecg.modules.simulator.model.train.event.msg.Train2StationMsg;
import org.jeecg.modules.simulator.util.SimulatorParamStr;
import org.jeecg.modules.simulator.util.SpringUtil;

import lombok.Data;
import lombok.Setter;
import org.jeecg.modules.simulator.vo.TrainPosition;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * @program: gp
 * @description: 列车主类
 * @author: renzhg
 * @create: 2024-08-07 09:30
 **/
@Slf4j
@Data
public class MetroTrain {
    private static final Logger logger = LoggerFactory.getLogger(MetroTrain.class);

    /**
     * 静态属性
     */
    String trainId;//车辆编号
    String trainNum;//车次号
    String groupId;//车辆箱体号
    String belongLineId;//上线后所属的线路编号
    TrainInfo trainInfo;
    TrainPhysics trainPhysics;
    TrainBiz trainBiz;


    @Setter
            @Getter
    Boolean isRuningUp;//运行是否上行

    /**
     * @description: 记录所有执行的过的动作，
     *
     * @author:  renzhg
     * @date:  2024/8/12 14:49
     **/
    Map<Integer,TrainActionRecorder> recorderMap=new HashMap<>();
    /**
     * @description:速度是用来计算距离的，比如给定时间，时间*速度，就知道处于什么位置了
     *
     * @author: renzhg
     * @date: 2024/8/5 10:02
     **/
    Long currentTrainSpeed;
    Long currentOffset;
    Integer accumulatedOffset=0;

    /**
     * 功能描述：时间计数器
     *
     * @author  renowen2005
     * @date  2024/07/24 17:30
     */
    @Setter
    private Long timeCounter;

    @Setter
    private  LocalTime actionEndTime;

//    TrainCounter trainCounter=new TrainCounter();
//key为客流OD

    private  Map<String, List<Person>> personMap = new HashMap<>();
    //    private Map<String, PassengerFlow> passengerFlowMap = new HashMap<>();
    private TrainActionRecorder currentTrainActionRecorder;
    public static final String ACTION_RUN = "run";
    public static final String ACTION_STOP = "stop";
    public static final String AFFILIATE_TYPE_DOCKING = "docking";

    String actionName="";



    /**
     * 添加客流
     *
     * @param key
     * @param passengerFlow
     */
    public void addPassengerFlow(String key, List<Person> passengerFlow) {
        synchronized (personMap) {
            Map<String, List<Person>> newPassengerFlowMap = new HashMap<>(personMap);
            newPassengerFlowMap.put(key, passengerFlow);
            personMap.putAll(newPassengerFlowMap);
        }
    }


    public TrainPosition getCurrentTrainPosition(String trainId,String belongLineId,String trainNum,String time,String tableItemName,String vid){

String key=this.currentTrainActionRecorder.getName();
        OrbitPoint orbitPoint =this.trainBiz.getOrbitPoint(key);
//        if(orbitPoint.getOrbitName().equals("沈阳南站-城建学院")&&time.equals("05:56:20")){
//            System.out.println("fdasfas");
//        }
        TrainPosition trainPosition = new TrainPosition();
        trainPosition.setTrainId(trainId);
        trainPosition.setTrainNum(trainNum);
        trainPosition.setOrbitAttr(orbitPoint,tableItemName,vid);
        trainPosition.setLineId(this.belongLineId);
        trainPosition.setPositionRatio(new BigDecimal(0));
        trainPosition.setCurTime(time);
        trainPosition.setCurrentOpt(this.trainBiz.getCurrentOpt());
        if(this.currentTrainActionRecorder.getAffiliateType()==null){
            System.out.println("lkf;adlsk;lfadk");
        }
        if(this.currentTrainActionRecorder.getAffiliateType().equals(SimulatorParamStr.ACTION_DOCKING)){
            trainPosition.setPositionRatio(new BigDecimal(0));
        }else if(this.currentTrainActionRecorder.getAffiliateType().equals(SimulatorParamStr.ACTION_RUN)){
            BigDecimal bigDecimal = this.trainBiz.caculateRatio(orbitPoint);
            trainPosition.setPositionRatio(bigDecimal);
        }

//        TrainPosition currentPosition = this.trainBiz.getCurrentPosition(trainId, belongLineId, trainNum, time);

        return trainPosition;
    }

    /**
     * 移除客流
     *
     * @param key
     */
    public void removePassengerFlow(String key) {
        synchronized (personMap) {
//            Map<String, List<Person>> newPassengerFlowMap = new HashMap<>(personMap);
//            newPassengerFlowMap.remove(key);
//            personMap = newPassengerFlowMap;
            personMap.remove(key);
        }
    }
    /**
     * @description:
     * @author: renzhg
     * @date: 2024/7/25 14:18
     * @return: java.util.Map<java.lang.String, com.miaohy.demo.vo.newventity.scene.model.PassengerFlow.PassengerFlow>
     **/
    public Map<String, List<Person>> getPassengerFlowMap() {
        synchronized (personMap) {
            return Collections.unmodifiableMap(personMap);
        }
    }
    //region 提供的外围服务的方法
    String getMaxFullLoad() {
        return trainPhysics.getMaxFullLoad();
    }

    /**
     * 获取当前车辆满载率
     *
     * @return
     */
    public String getFullLoad() {
//        double value = Double.parseDouble(trainPhysics.getMaxFullLoad().replace("%", "")) / 100;

        int coutTotalPS=countTotalPersons();
        int capacity=trainPhysics.getCapacity();
        double result = (double)coutTotalPS /capacity;
        DecimalFormat df = new DecimalFormat("#.###");
        String formattedResult = df.format(result);
//        double ratio =  (double)(countTotalPersons()/ trainPhysics.getCapacity());
        return formattedResult;

    }
    /**
     * @description: 计算列车中的总人数。
     *
     * @author:  renzhg
     * @date:  2024/9/19 19:11
     **/
    public  int countTotalPersons() {
        int count = 0;

        // 遍历 map 的每一个 entry
        for (List<Person> persons : personMap.values()) {
            if (persons != null) {
                count += persons.size(); // 累加每个 List<Person> 的大小
            }
        }

        return count; // 返回总计数
    }


    //region 车辆行驶信息
//    public TrainPosition getTrainPositionByTrainIdNum(LocalTime now) {
//        return trainBiz.getCurrentPosition(this.trainId,this.trainNum, now);
//    }




    //endregion

//region 获取当前车站的站名

//    public int currentAllPfNums() {
//        return trainCounter.currentAllPfNums(
//                personMap.values().stream().
//                passengerFlowMap.values().stream().collect(Collectors.toList()));
//    }
//
//    public int currentPfTransferNums() {
//        return trainCounter.currentPfTransferNums(passengerFlowMap.values().stream().collect(Collectors.toList()));
//    }
//
//    public int currentPfExitNums() {
//        return trainCounter.currentPfExitNums(passengerFlowMap.values().stream().collect(Collectors.toList()));
//    }
//
//    public int currentPfNums() {
//        return trainCounter.currentPfExitNums(passengerFlowMap.values().stream().collect(Collectors.toList()));
//    }


//endregion

    //设置在某一个时间点列车的运行状态
    public void setOneTimePtInitTrainStatue(TrainActionRecorder trainActionRecorder,LocalTime now){
        currentTrainActionRecorder=trainActionRecorder;
        currentTrainActionRecorder.setFinished(false);
        String action = trainActionRecorder.getAction();
        // 空值检查
        if (action == null) {
            // 根据实际情况处理空值情况，例如记录日志、抛出异常或返回错误
            throw new IllegalArgumentException("Train action cannot be null");
        }
        Long recorderDuring = trainActionRecorder.getDuring();
        //当前时间点的偏移距离
        Duration subDuration = Duration.between(trainActionRecorder.getStartTime(), now);
        long sebSeconds = subDuration.getSeconds();//
        switch (action) {
            case ACTION_RUN:
                actionName= trainActionRecorder.getName();
                setOneTimePtSectInit(sebSeconds,recorderDuring,trainActionRecorder.getName());
                break;
            case ACTION_STOP:
                setOneTimePtStopInit(sebSeconds,recorderDuring);
                break;
            default:
                // 处理未知动作的情况
                // 可以记录日志、抛出异常或忽略
                throw new IllegalArgumentException("Unknown train action: " + action);
        }
    }

    //region 列车运行的方法
    /**
     * 功能描述：上车计算，是否能上车,暂时留着
     *
     * @param willNumds
     * @return boolean
     * @author renowen2005
     * @date 2024/07/24 16:31
     */
    public Boolean recordOffTrain(Integer willNumds) {

        return ((currentAllPfNums() + willNumds) / trainPhysics.getCapacity()) < convertPercentageToDouble(trainPhysics.getMaxFullLoad());
    }

    public  double convertPercentageToDouble(String percentageString) {
        // Remove the '%' symbol
        String numberString = percentageString.replace("%", "");

        // Convert the resulting string to a double
        double value = Double.parseDouble(numberString);

        // Format to two decimal places (optional, depending on use case)
        return Math.round(value * 100.0) / 100.0;
    }

//
    /**
     * @description: 车上所有人数
     *
     * @author:  renzhg
     * @date:  2024/9/12 10:28
     **/

    private int currentAllPfNums(){
        return personMap.values().stream()
                .mapToInt(List::size) // 将每个 List 的大小映射为 long
                .sum(); // 计算总和
    }

    public TrainRunState getTrainRunState() {
        return trainBiz.getState();
    }


    //endregion




    /**
     * @description: 在一个动作内的偏移距离是多少
     *
     * @author:  renzhg
     * @date:  2024/8/12 13:50
     **/
    public Long getInActtionOfOffset(){
        return trainBiz.getCurActionOffset(this.timeCounter);
    }





    /**
     * @description: 执行动作
     * @author: renzhg
     * @date: 2024/7/29 15:28
     * @param : trainActionRecorder
     **/
    public void processTrainAction(TrainActionRecorder trainActionRecorder,String now) {
        if(this.getTrainId().equals("lsAdd01")){
            logger.debug("当前时间："+now);
        }

        if(now.toString().equals("08:00:57")){
            logger.debug("当前时间："+now);
        }

        if(trainActionRecorder.getName().equals("创新路-沈阳南站")){
            System.out.println("创新路-沈阳南站");
        }
        currentTrainActionRecorder=trainActionRecorder;
        currentTrainActionRecorder.setFinished(false);
        String action = trainActionRecorder.getAction();

        // 空值检查
        if (action == null) {
            // 根据实际情况处理空值情况，例如记录日志、抛出异常或返回错误
            throw new IllegalArgumentException("Train action cannot be null");
        }
        switch (action) {
            case ACTION_RUN:
                if(trainActionRecorder.getName().contains("end")){
                    simpleRun(trainActionRecorder);
                    return;
                }
                normalRun(trainActionRecorder);
                break;
            case ACTION_STOP:
                stopStation(trainActionRecorder, now);
                break;
            default:
                // 处理未知动作的情况
                // 可以记录日志、抛出异常或忽略
                throw new IllegalArgumentException("Unknown train action: " + action);
        }
    }

    /**
     * @description: 处理列车在车站的停止动作
     * 1、获取停靠点名称
     * 2、设定停止时间
     * 3、发送停车消息
     *
     * @author:  renzhg
     * @date:  2024/9/24 9:05
     **/
    private void stopStation(TrainActionRecorder trainActionRecorder, String now) {
        String affiliateType = trainActionRecorder.getAffiliateType();
        actionName= trainActionRecorder.getName();
        this.trainBiz.setCurrentSectName("");
        // 对getAffiliateType的空值检查
        if (affiliateType != null && affiliateType.equals(AFFILIATE_TYPE_DOCKING)) {
            setDockingStop(trainActionRecorder.getDuring());
            sendStopMsg(trainActionRecorder.isLast(), now);
        }


    }

    /**
     * @description: 简单运行，全线路段运行
     *
     * @author:  renzhg
     * @date:  2024/9/20 9:29
     **/
    private void simpleRun(TrainActionRecorder trainActionRecorder) {
        actionName= trainActionRecorder.getName();
        double actualSpeed = trainActionRecorder.getActualSpeed();
        Long timeInSeconds=trainBiz.getAllOrbitLength();


        Long timeCount = trainBiz.initSimpleStart(actualSpeed);
//        if (timeInSeconds < 0) {
//            throw new IllegalArgumentException("时间不能为负数");trainBiz
//        }


        setTimeCounter(Math.abs(timeCount));
        trainBiz.setLastState(trainBiz.getState());
        trainBiz.setState(TrainRunState.nextrun);
        trainActionRecorder.setPlanSpeed( Math.round(trainBiz.getCurrentSpeed()));
        currentOffset=trainBiz.getAllOrbitLastOffset();


        //1、把整个轨道给TrainBiz--完成
        //2、根据轨道长度除以速度，得到时间，有了时间就设定时间倒数计数--完成
        //3、根据速度和长度计算sublevelList--晚点
        //
    }

    private void normalRun(TrainActionRecorder trainActionRecorder) {
        String sectName = trainActionRecorder.getName();
        if(sectName.equals("向工街-塔湾街")&&this.trainNum.equals("01")&&this.trainId.equals("103")&&this.belongLineId.equals("10")){
            System.out.println("normalrune");
        }

        actionName= trainActionRecorder.getName();
        this.actionEndTime=trainActionRecorder.getEndTime();
        move(trainActionRecorder.getDuring(),sectName);
        trainActionRecorder.setPlanSpeed( Math.round(trainBiz.getCurrentSpeed()));
        currentOffset=trainBiz.getOffset(sectName);
//        logger.debug("当前列车编号："+this.trainId+"_"+this.trainNum);
//        logger.debug("当前动作："+trainActionRecorder.getAction());
//        logger.debug("动作位置:"+trainActionRecorder.getName());
//        logger.debug("当前位置："+currentOffset);
    }

    /**
     * @description: 停车发车停车消息
     *
     * @author:  renzhg
     * @date:  2024/9/10 10:44
     **/
    private void sendStopMsg(boolean isLast,String now) {
        LocalTime localTime = LocalTime.parse(now);
        Train2StationMsg train2StationMsg = new Train2StationMsg();
        train2StationMsg.setStopStationName(actionName);
        train2StationMsg.setBelongLineId(this.belongLineId);
        train2StationMsg.setUp(isRuningUp);
        train2StationMsg.setLast(isLast);
        train2StationMsg.setTime(localTime);
        train2StationMsg.setTrain(this);
        SpringUtil.getApplicationContext().publishEvent(new TrainStopEvent(train2StationMsg));
    }


    public void setOneTimePtStopInit(Long subDurring,Long recorderDurring){
        trainBiz.setLastState(TrainRunState.nextrun);
        trainBiz.setState(TrainRunState.stop);
        this.timeCounter=recorderDurring-subDurring;

    }




    public void setOneTimePtSectInit(Long subDurring,Long recorderDurring,String sectName){
        try {

            trainBiz.initOneTimePtSectStart(sectName,recorderDurring,subDurring);

            setTimeCounter(subDurring);
        } catch (Exception e) {
            // 根据实际情况处理或记录异常，这里仅打印堆栈跟踪
            e.printStackTrace();
        }

    }

    /**
     * 将时间计数器设置为指定的秒数，并更新火车运行状态。
     *
     * @param timeInSeconds 要设置的时间，以秒为单位。
     */
    public void move(Long timeInSeconds,String sectName) {
        // 参数有效性检查
        if (timeInSeconds < 0) {
            throw new IllegalArgumentException("时间不能为负数");
        }
        // 尝试执行操作，并捕获可能的异常
        try {
            setTimeCounter(timeInSeconds);
            trainBiz.initStart(sectName,timeInSeconds);
            trainBiz.setLastState(trainBiz.getState());
            trainBiz.setState(TrainRunState.nextrun);
//            this.timeCounter--; // 确保操作在异常处理中不会导致未定义行为
        } catch (Exception e) {
            // 根据实际情况处理或记录异常，这里仅打印堆栈跟踪
            e.printStackTrace();
        }
        // 边界条件检查
        if (this.timeCounter < 0) {
            // 处理timeCounter变为负数的情况，例如重置为0或记录错误
            this.timeCounter = 0L; // 假设我们选择重置为0
        }
    }




    /**
     * 功能描述：给定时间停止
     *
     * @param timeCounterValue 用于设置时间计数器的值
     * @author renowen2005
     * @date 2024/07/24 17:50
     */
    public void setDockingStop(Long timeCounterValue) {
        try {
            // 参数校验
            if (timeCounterValue < 0) {
                throw new IllegalArgumentException("时间计数器值不能为负数");
            }
            // 更新火车状态
            TrainRunState lastState = trainBiz.getState();
            trainBiz.setLastState(lastState);
            trainBiz.setState(TrainRunState.stop);
            this.timeCounter=timeCounterValue;
            // 减少时间计数器的值，保证线程安全
            /**这个地方有问题=====================================================
             * @description:
             *
             * @author: renzhg
             * @date: 2024/7/29 17:04
             **/

        } catch (Exception e) {
            // 异常处理逻辑，例如记录日志等
            // 此处需要根据实际情况来处理异常，以确保程序的健壮性
            logger.debug("设置停靠停止时发生异常: " + e.getMessage());
        }
    }
    /**
     * 场景接口
     */
    public void update(String now, TrainActionRecorders trainActionRecorders) {
//        TimeUtil.printLcaltime(now);
        if(this.getTrainId().equals("103")&&this.trainNum.equals("01")&&this.getBelongLineId().equals("10")){
            logger.debug("当前时间："+now);
        }
        LocalTime localTime = LocalTime.parse(now);
        if(localTime.isBefore(trainActionRecorders.getFistActionTime())){
            return;
        }
//        System.out.println("当前speed:"+this.trainBiz.getCurrentSpeed());
//        System.out.println("getCurrentSectName:"+this.trainBiz.getCurrentSectName());
//        System.out.println("update,e:"+this.getTrainId()+"_"+this.getTrainNum());

        if(this.timeCounter>0&&localTime.isBefore(trainActionRecorders.getCurrentTrainActionRecorder().getEndTime())){
            if(this.getTrainId().equals("103")&&this.trainNum.equals("01")&&this.getBelongLineId().equals("10")){
                    System.out.println(trainActionRecorders.getCurrentTrainActionRecorder().getName());
                System.out.println("当前时间："+now);
                System.out.println("当前时间："+this.timeCounter);

            }
            trainBiz.update(localTime,trainActionRecorders.getCurrentTrainActionRecorder().getEndTime());
            this.timeCounter--;
        }else if(localTime.equals(trainActionRecorders.getCurrentTrainActionRecorder().getEndTime())){


            if(this.currentTrainActionRecorder==null){
                return;
            }
            this.currentTrainActionRecorder.setFinished(true);
            this.currentTrainActionRecorder.setExecutionStatus(ExecutionStatus.succeed);
        }

    }


    /**
     * @description: 得到当前事件的执行状态
     * @author: renzhg
     * @date: 2024/7/29 15:58
     * @return:
     **/
    public ExecutionStatus getCurrentExecutionStatus() {
        if(currentTrainActionRecorder==null){
            return ExecutionStatus.initialize;
        }
        return currentTrainActionRecorder.getExecutionStatus();
    }



}
